package modelo;

import java.util.ArrayList;
import java.util.List;

import excepciones.BarcoEstaAlBordeExcepcion;
import excepciones.TableroIndiceFueraDeRangoExcepcion;

public class GeneradorDeMovimientos {
	// Se podria agregar un atributo como "camino", "ruta" o "listaDeMovimientos", que
	// tenga una sequencia de movimientos a ser seguidos en cada mover().
	private Direccion direccion;
    
	public GeneradorDeMovimientos(Direccion unaDireccion){
		direccion = unaDireccion;
	}
	
    public ArrayList<Posicion> mover(Tablero tablero, Barco barco) {
    	ArrayList<Posicion> posiciones = null;
    	// Trata de avanzar una posicion, si esta al borde da vuelta el barco.
    	try {
    		posiciones = avanzar(tablero,barco,barco.getPosiciones());
    	}
    	catch (BarcoEstaAlBordeExcepcion unError) {
    		posiciones = darVuelta(barco);
    		try {
				posiciones = avanzar(tablero,barco,posiciones);
			}
    		catch (BarcoEstaAlBordeExcepcion e) {
				e.printStackTrace();
			}
    	}
		return posiciones;
    }

    private ArrayList<Posicion> avanzar(Tablero tablero, Barco barco,List<Posicion> posiciones) throws BarcoEstaAlBordeExcepcion {
      	// Va guardando en un vector las posiciones nuevas y controla que el barco no este al borde del tablero.
    	ArrayList<Posicion> nuevasPosiciones = new ArrayList<Posicion>();
		try {
			for(int i=0; i<posiciones.size(); i++){
				Posicion posicionActual = posiciones.get(i);
				int filaDeLaSiguientePosicion = posicionActual.getFila()+ direccion.getFactorDeAumentoDeFila();
				int columnaDeLaSiguientePosicion = posicionActual.getColumna()+ direccion.getFactorDeAumentoDeColumna();
				Posicion posicionSiguiente = tablero.getPosicion(filaDeLaSiguientePosicion,columnaDeLaSiguientePosicion);
				nuevasPosiciones.add(posicionSiguiente);
			}
		}
		catch (TableroIndiceFueraDeRangoExcepcion unError) {
			throw new BarcoEstaAlBordeExcepcion("ERROR: El barco no puede avanzar.");
		}
		// Si avanza de casillero, avisa a las de las que se movio que ya no esta ahi,
		// y avisa a las nuevas posiciones que esta en ese lugar.
		for (int i = 0; i < posiciones.size(); i++) {
			(posiciones.get(i)).quitarBarco(barco);
			(nuevasPosiciones.get(i)).agregarBarco(barco);
		}
		return nuevasPosiciones;
	}

	private ArrayList<Posicion> darVuelta(Barco barco) {
		ArrayList<Posicion> nuevasPosiciones = new ArrayList<Posicion>();
		ArrayList<Parte> nuevasPartes = new ArrayList<Parte>();
		// Da vuelta el barco.
		int tamanio = barco.getPosiciones().size();
		for (int i = 0; i < tamanio; i++){
			Posicion posicionAuxiliar = barco.getPosiciones().get(tamanio-1-i);
			nuevasPosiciones.add(posicionAuxiliar);
			Parte parteAuxiliar = barco.getPartes().get(tamanio-1-i);
			nuevasPartes.add(parteAuxiliar);
		}
		// Cambia la direccion.
		direccion = direccion.getDireccionOpuesta();
		barco.setPartes(nuevasPartes);
		
		return nuevasPosiciones;
	}

	public Direccion getDireccion() {
		return direccion;
	}
}
